#include "ringBuffer.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>

/**
 * @function:   线程清理函数，防止线程带锁退出
 */
// static void handler(void *arg){
// 	pthread_mutex_unlock((pthread_mutex_t *)arg);//解锁
// }

/**
 *  Function:   ringBuf_init()
 *  Description:循环缓冲区初始化函数
 *  Access Level:   public
 *  Input:      bufSize--循环缓冲区大小
 *  Output:     N/A
 *  Return:     循环缓冲区句柄--成功/NULL--失败
 */
HANDLE ringBuf_init(int bufSize)
{
    if(bufSize <= 0){
        return NULL;
    }

    unsigned char *bufBase = NULL;
    ringBuffer *hRingBuf = NULL;

    bufBase = (u_int8_t *)calloc(1,bufSize);
    assert(bufBase != NULL);


    hRingBuf = (ringBuffer *)calloc(1,sizeof(ringBuffer));
    assert(hRingBuf != NULL);

    hRingBuf->bufBase = bufBase;
    hRingBuf->bufLen = bufSize;
    hRingBuf->writeIdx = 0;
    hRingBuf->readIdx = 0;
    hRingBuf->dataLen = 0;
    pthread_mutex_init(&hRingBuf->mutex,NULL);
    pthread_cond_init(&hRingBuf->read_cont,NULL);
    pthread_cond_init(&hRingBuf->write_cont,NULL);
    hRingBuf->bSafe = true;

    return hRingBuf;
}

/**
 *  Function:   ringBuf_write()
 *  Description:循环缓冲区写入函数
 *  Input:      hRingBuf--循环缓冲区句柄
 *              pSrcBuf--待写入数据源地址
 *              len--待写入数据长度
 *  Output:     N/A
 *  Return:    实际写入数据的长度--成功/0--失败
 */
int ringBuf_write(HANDLE hRingBuf,unsigned char *pSrcBuf,int len)
{
    assert(hRingBuf != NULL);
    int writed = 0;//已写字节数

#if IS_THREAD_SAFE
    /* 注册一个线程清理函数，防止死锁 */
    //pthread_cleanup_push(handler, (void *)&hRingBuf->mutex);
    pthread_mutex_lock(&hRingBuf->mutex);

    //环形缓冲区空间不足以写下len个字节
    while(hRingBuf->bufLen-hRingBuf->dataLen < len){
        pthread_cond_wait(&hRingBuf->write_cont,&hRingBuf->mutex);
    }
#endif

    while(writed < len && hRingBuf->dataLen < hRingBuf->bufLen){
        hRingBuf->bufBase[hRingBuf->writeIdx++]=*(pSrcBuf++);
        writed++;
        hRingBuf->dataLen++;
        hRingBuf->writeIdx = hRingBuf->writeIdx%hRingBuf->bufLen;
    }

#if IS_THREAD_SAFE
    pthread_mutex_unlock(&hRingBuf->mutex);
    pthread_cond_signal(&hRingBuf->read_cont);     //唤醒一个等待去写的线程
#endif

    return writed;
}

/**
 *  Function:   ringBuf_read()
 *  Description:循环缓冲区读取数据函数
 *  Input:      hRingBuf--循环缓冲区句柄
 *              pDstBuf--读取数据的目的地址
 *              len--待读取数据长度
 *  Output:     N/A
 *  Return:     实际读取数据的长度--成功/-1--失败
 */
int ringBuf_read(HANDLE hRingBuf,unsigned char* pDstBuf,int len)
{
    assert(hRingBuf != NULL);
    int reads = 0;//已读节数
#if IS_THREAD_SAFE
    /* 注册一个线程清理函数，防止死锁 */
    //pthread_cleanup_push(handler, (void *)&hRingBuf->mutex);
    pthread_mutex_lock(&hRingBuf->mutex);
    while(hRingBuf->dataLen < len)
        pthread_cond_wait(&hRingBuf->read_cont,&hRingBuf->mutex);
#endif

    while(hRingBuf->dataLen && reads<len){
        *(pDstBuf++) = hRingBuf->bufBase[hRingBuf->readIdx++];
        reads++;
        hRingBuf->dataLen--;
        hRingBuf->readIdx = hRingBuf->readIdx%hRingBuf->bufLen;
    }

#if IS_THREAD_SAFE
    pthread_mutex_unlock(&hRingBuf->mutex);
    pthread_cond_signal(&hRingBuf->write_cont);     //唤醒一个等待去写的线程
#endif

    return reads;
}

/**
 *  Function:   ringBuf_dateLen()
 *  Description:获取循环缓冲区有效数据长度
 *  Input:      hRingBuf--循环缓冲区句柄
 *  Output:     N/A
 *  Return:     循环缓冲区有效数据长度--成功/-1--失败
 */
int ringBuf_dateLen(HANDLE hRingBuf)
{
    assert(hRingBuf != NULL);

#if IS_THREAD_SAFE
    /* 注册一个线程清理函数，防止死锁 */
    //pthread_cleanup_push(handler, (void *)&hRingBuf->mutex);
    pthread_mutex_lock(&hRingBuf->mutex);
#endif

    int len = hRingBuf->dataLen;

#if IS_THREAD_SAFE
    pthread_mutex_unlock(&hRingBuf->mutex);
#endif
    return len;
}
/**
 *  Function:   ringBuf_bufferRemain()
 *  Description:获取循环缓冲区可写长度
 *  Input:      hRingBuf--循环缓冲区句柄
 *  Output:     N/A
 *  Return:     循环缓冲区有效数据长度--成功/-1--失败
 */
int ringBuf_bufferRemain(HANDLE hRingBuf)
{
    assert(hRingBuf != NULL);
#if IS_THREAD_SAFE
    /* 注册一个线程清理函数，防止死锁 */
    //pthread_cleanup_push(handler, (void *)&hRingBuf->mutex);
    pthread_mutex_lock(&hRingBuf->mutex);
#endif
    int len = hRingBuf->bufLen - hRingBuf->dataLen;

#if IS_THREAD_SAFE
    pthread_mutex_unlock(&hRingBuf->mutex);
#endif
    return len;
}

/**
 *  Function:   ringBuf_destroy()
 *  Description:循环缓冲区销毁函数
 *  Input:      hRingBuf--循环缓冲区句柄
 *  Output:     N/A
 *  Return:     OK/ERROR
 */
int ringBuf_destroy(HANDLE *hRingBuf)
{
    assert(*hRingBuf != NULL);
#if IS_THREAD_SAFE
    pthread_mutex_lock(&((*hRingBuf)->mutex));
#endif

    HANDLE p = *hRingBuf;
    *hRingBuf = NULL;

#if IS_THREAD_SAFE
    pthread_mutex_unlock(&(p->mutex));//先解锁再释放，避免线程死锁
#endif

    free(p);

    return OK;
}